import { Injectable } from '@angular/core';
import { STColumn, STData } from '@delon/abc';
import { SupDic } from 'lbf';
import { from } from 'rxjs';
import { groupBy, mergeMap, toArray, map, reduce, mergeAll } from 'rxjs/operators';
import { group } from '@angular/animations';
import { element, FileDetector } from 'protractor';

@Injectable({ providedIn: 'root' })
export class SupData {

  constructor(private supdic: SupDic) { }

  calcbyopeartor(val, val1, operator) {
    if (!val) val = 0
    if (!val1) val1 = 0
    switch (operator) {
      case '+':
        return val + val1;
      case '-':
        return val - val1;
      case '*':
        return val * val1;
      case '/':
        return val / (val1 === 0 ? val : val1)
    }
  }

  isBrackets(operator) {
    return ['(', ')'].indexOf(operator) > -1
  }

  isOperator(operator) {
    return ['+', '-', '*', '/'].indexOf(operator) > -1
  }

  isItem(operator) {
    return typeof operator === 'string' && operator.startsWith('I')
  }

  infixToSuffix(formarr) { // 中缀转后缀
    const temp = []
    const opertors = []
    formarr.forEach(ele => {
      if (this.isItem(ele)) { // 指标数组中的值
        temp.push(ele)
      } else if (this.isBrackets(ele)) { // 括号
        if (ele === '(') {
          opertors.push(ele)
        } else if (ele === ')') {
          let popOperator
          while (opertors.length > 0 && popOperator !== '(') {
            popOperator = opertors.pop()
            if (popOperator !== '(') temp.push(popOperator)
          }
        }
      } else if (this.isOperator(ele)) { // 操作符， 有优先级
        if (['+', '-'].indexOf(ele) > -1) { // 当前操作符
          while (opertors.length > 0 && ['('].indexOf(opertors[opertors.length - 1]) < 0) {
            // 栈顶操作符优先级比较大
            const topOperator = opertors.pop()
            temp.push(topOperator)
          }
          opertors.push(ele)
        } else if (['*', '/'].indexOf(ele) > -1) {
          while (opertors.length > 0 && ['+', '-', '('].indexOf(opertors[opertors.length - 1]) < 0) {
            // 栈顶操作符优先级比较大
            const topOperator = opertors.pop()
            temp.push(topOperator)
          }
          opertors.push(ele)
        }
      } else { // 固定值
        temp.push(parseFloat(ele))
      }
    })
    while (opertors.length > 0) {
      const topOpertor = opertors.pop()
      temp.push(topOpertor)
    }
    return temp
  }

  suffixCalc(suffix) { // 计算后缀表达式
    const vals = [] // 值堆栈
    suffix.forEach(ele => {
      if (typeof ele === 'number') {
        vals.push(ele)
      } else {
        const val1 = vals.pop()
        const val = vals.pop()
        vals.push(this.calcbyopeartor(val, val1, ele))
      }
    })
    let result = vals[0]
    const xsw = result.toString().split('.')[1]
    if (xsw !== undefined && xsw.length > 2) {
      result = Math.round(result * 100) / 100
    }
    return result
  }

  rescalc(resjson: any, feild: any, formula: string, dx: string, dz: string) {
    if (!formula) return resjson

    let _formula = formula
    const formarr = []
    const regvalue = /\+|\-|\*|\/|\(|\)|(?:0\.\d*[1-9]|[1-9]\d*(?:\.\d*[1-9])?)|I[0-9]+/
    while (_formula.trim()) {
      const mat = _formula.match(regvalue)
      formarr.push(mat[0])
      _formula = _formula.substring(mat[0].length + mat.index)
    }
    // formula.split(regvalue)
    const templist = []
    let maxLength = 0
    formarr.forEach(ele => {
      if (this.isItem(ele)) {
        maxLength = resjson[ele.substring(1)].list.length > maxLength ? resjson[ele.substring(1)].list.length : maxLength
      }
    })

    if (!dx && !dz) {
      for (let i = 0; i < maxLength; i++) {
        const forma = formarr.map(ele => {
          if (this.isItem(ele)) {
            return resjson[ele.substring(1)].list[i] ? resjson[ele.substring(1)].list[i].VAL : 0
          }
          return ele
        })
        templist.push({
          VAL: this.suffixCalc(this.infixToSuffix(forma))
        })
      }
    } else if (dx || dz) {
      let col = dx || dz
      for (let i = 0; i < maxLength; i++) {
        let colstr, errorflag = false
        const forma = formarr.map(ele => {
          if (errorflag) return
          if (this.isItem(ele)) {
            if (colstr) {
              const elseobj = resjson[ele.substring(1)].list.find(item => item && item[col] === colstr)
              if (elseobj) {
                return elseobj ? elseobj.VAL : 0
              } else {
                errorflag = true
                return
              }
            } else {
              const firstobj = resjson[ele.substring(1)].list[i]
              if (firstobj) {
                colstr = firstobj[col]
                return firstobj ? firstobj.VAL : 0
              } else {
                errorflag = true
                return
              }
            }
          }
          return ele
        })
        if (!errorflag)
          templist.push({
            [col]: colstr,
            VAL: this.suffixCalc(this.infixToSuffix(forma))
          })
      }

    } else if (dx && dz) {
      let dxcol = dx, dzcol = dz
      for (let i = 0; i < maxLength; i++) {
        let dxcolstr, dzcolstr, errorflag = false
        const forma = formarr.map(ele => {
          if (errorflag) return
          if (this.isItem(ele)) {
            if (dxcolstr && dzcolstr) {
              const elseobj = resjson[ele.substring(1)].list.find(item => item && item[dxcol] === dxcolstr && item[dzcol] === dzcolstr)
              if (elseobj) {
                return elseobj ? elseobj.VAL : 0
              } else {
                errorflag = true
                return
              }
            } else {
              const firstobj = resjson[ele.substring(1)].list[i]
              if (firstobj) {
                dxcolstr = firstobj[dxcol]
                dzcolstr = firstobj[dzcol]
                return firstobj ? firstobj.VAL : 0
              } else {
                errorflag = true
                return
              }
            }
          }
          return ele
        })
        if (!errorflag)
          templist.push({
            [dxcol]: dxcolstr,
            [dzcol]: dzcolstr,
            VAL: this.suffixCalc(this.infixToSuffix(forma))
          })
      }
    }


    resjson[feild.key] = {
      list: templist,
      DAA022: feild.name||feild.key
    }
    return resjson
    // return row[field];
  }

  // todo 四则计算
  // 1、提取最里层括号里面的内容
  // 2、计算最里层括号内的乘除运算，并将结果替换到原表达式
  // 3、循环执行前两步的结果
  calc(row: any, field: string, formula: string) {

    // const patt = '\(([^()]+)\)';

    if (!formula) return row[field];

    if (formula.includes("*")) {
      const strs: string[] = formula.split('*');
      const val: number[] = [];
      strs.forEach(s => {
        if (s.startsWith("I")) {
          val.push(row[s.substring(1)] ? row[s.substring(1)] : 0);
        } else {
          val.push(Number.parseFloat(s))
        }

      })
      return Math.round(val[0] * val[1]);
    }

    if (formula.includes("/")) {
      const strs: string[] = formula.split('/');
      const val: number[] = [];
      strs.forEach(s => {
        if (s.startsWith("I")) {
          val.push(row[s.substring(1)] ? row[s.substring(1)] : 0);
        } else {
          val.push(Number.parseFloat(s))
        }

      })
      return val[1] === 0 ? 0 : Math.round(val[0] / val[1] * 100) / 100;
    }

    if (formula.includes("+")) {
      const strs: string[] = formula.split('+');
      const val: number[] = [];
      strs.forEach(s => {
        if (s.startsWith("I")) {
          val.push(row[s.substring(1)] ? row[s.substring(1)] : 0);
        } else {
          val.push(Number.parseFloat(s))
        }

      })
      return Math.round(val[0] + val[1] * 100) / 100;
    }

    if (formula.includes("-")) {
      const strs: string[] = formula.split('-');
      const val: number[] = [];
      strs.forEach(s => {
        if (s.startsWith("I")) {
          val.push(row[s.substring(1)] ? row[s.substring(1)] : 0);
        } else {
          val.push(Number.parseFloat(s))
        }

      })
      return Math.round((val[0] - val[1]) * 100) / 100;
    }

    return row[field];

  }


  getValFileds(tb: any, data: any) {

    let fileds: string[] = tb.DAA035.split(',');
    const dae005 = tb.DAE005;
    // 如果未配置显示信息，则就是本身,否则删除
    if (dae005 && Object.keys(dae005).length > 0) {
      fileds = fileds.filter(f => dae005[f]);
    }

    // 转化成中文信息
    // const newFileds = [];
    // fileds.forEach(f => {
    //   if (data[f]) {
    //     newFileds.push(data[f].DAA022);
    //   }

    // })


    return fileds;

  }

  /**
   * 数据分组
   * @param data 源数据
   * @param groupby 分组字段
   * @param orderby 排序字段
   */
  dataPartition(data: any[], groupby: string, valfiled: string) {

    const { DataView } = DataSet;
    let dv = new DataView().source(data);
    dv.transform({
      type: 'partition',
      groupBy: [groupby], // 以year字段进行分组
    });

    const tmpdata = dv.rows;
    const newdata = [];
    const fileds = [];
    const operations = [];

    Object.keys(tmpdata).forEach(key => {
      tmpdata[key].forEach(elem => {
        elem[key.substring(1)] = elem[valfiled];
        delete elem[valfiled]
        delete elem[groupby]
        Object.keys(tmpdata).forEach(key2 => {
          if (key !== key2) {
            elem[key2.substring(1)] = 0;
          }
        })


        newdata.push(elem);
      });
      fileds.push(key.substring(1))
      operations.push("sum");
    })

    dv = new DataView().source(newdata);

    dv.transform({
      type: 'aggregate', // 别名summary
      fields: fileds,        // 统计字段集
      operations,    // 统计操作集
      as: fileds,            // 存储字段集
      groupBy: ['DAA020']       // 分组字段集
    })

    return [dv.rows, fileds];
  }

  /**
   * 多字段合并，合并后的字段名默认为 DAA020 值
   * @param data 原数组
   * @param dataFilds 合并字段
   */
  dataFold(data: any[], dataFilds: string[], key?: string, valname?: string) {


    const { DataView } = DataSet;
    const dv = new DataView().source(data);
    if (!key) {
      key = "DAA020"
    }

    if (!valname) {
      valname = "值"
    }

    dv.transform({
      type: 'fold',
      fields: dataFilds,
      key,
      value: valname // value字段
    });

    data = dv.rows;
    return data;

  }

  /* 获取指标域
   * @param data 元数据
   * @returns 返回一个对象，keyfeild
   */
  getKeyFeild(resdata, ) {
    const keyfeild = []
    for (const key of Object.keys(resdata)) {
      keyfeild.push({
        name: resdata[key].DAA022,
        key,
      })
    }
    return keyfeild
  }

  /**
   * 数据分组
   * @param arr 要分组的数据
   * @param keyfeild 分组域
   */
  partition(arr, keyfeild) {
    const arrtemp = []
    arr.forEach(item => {
      keyfeild.forEach(ele => {
        arrtemp.push({
          ...item,
          item: ele.name,
          VAL: item[ele.key]
        })
      })
    })
    return arrtemp
  }

  /**
   * 数据处理，拉平 补全 分组求和
   * @param data 原始数据
   * @param fields 数据字段，数字字段将会自动补全以及根据分组字段汇总
   * @param groupFiedls 分组字段
   * @param orderFileds 排序字段
   * @param orderType 排序方式 默认为 ASC，DESC 则为逆序 
   */
  rebuildData(data: any, tb: any, groupFiedls: string[], orderFileds: string[] = [], orderType: string = 'ASC') {



    // 原始字段
    const fields: string[] = tb.DAA035.split(',');
    // // 指标字段
    // const cfileds: any[] = [];

    // fields.forEach(f => {
    //   if (data[f]) {
    //     cfileds.push({ DAA020: data[f].DAA020, DAA021: data[f].DAA021, DAA022: data[f].DAA022 });

    //   }

    // })

    const d: any[] = [];
    const operations = [];

    // 修改字段名称
    fields.forEach(f => {

      operations.push('sum');

      d.push(...data[f].list.map(m => {
        // 修改值对应的字段
        m[f] = m.VAL;
        delete m.VAL;
        // 其它字段补0
        fields.forEach(f2 => {
          if (f2 !== f)
            m[f2] = 0;
        })

        return m;
      }))
    });

    const { DataView } = DataSet;
    const dv = new DataView().source(d);

    dv.transform({
      type: 'aggregate', // 别名summary
      fields,        // 统计字段集
      operations,    // 统计操作集
      as: fields,            // 存储字段集
      groupBy: groupFiedls       // 分组字段集
    })

    if (orderFileds.length > 0) {

      dv.transform({
        type: 'sort-by',
        fields: orderFileds, // 根据指定的字段集进行排序，与lodash的sortBy行为一致
        order: orderType === 'ASC' ? 'ASC' : 'DESC'        // 默认为 ASC，DESC 则为逆序
      })
    }


    // 计算显示问题
    const dae005 = JSON.parse(tb.DAE005);
    // 如果未配置显示信息，则就是本身,否则删除

    if (dae005 && Object.keys(dae005).length > 0) {

      const orgData: any[] = dv.rows;

      orgData.map(row => {

        Object.keys(dae005).forEach((k: string) => {
          const dae = dae005[k];
          if (dae.J) {
            row[k] = this.calc(row, k, dae.J)
          }
          // 显示单位
          if (dae.D) {
            row[k] = row[k] + dae.D
          }

        })


        // Object.keys(dae005).forEach((k: string) => {
        //   const dae = dae005[k];
        //   if (dae.J) {
        //      row[k] =this.calc(row,k,dae.J)
        //   }
        //   // 显示单位
        //   if (dae.D) {
        //     row[k] = row[k] + dae.D
        //   }
        // })

        // 删除中间字段

      })



    }


    return dv.rows;
  }



  /**
   * 数组中字段的字典值转化
   * @param data 数组
   */
  rebuildDsDataToLabel(data: any) {

    return data.map(el => {

      Object.keys(el).forEach(key => {

        if (this.supdic.getDic(key).length > 0) {

          el[key] = this.supdic.getdicLabel(key, el[key]);
        }

      })
      return el;
    })
  }

  /**
   * 重命名数组的字段
   * @param data 数组
   * @param cols 字段信息
   */
  rebuildDsColums(data: any, cols: any) {

    const renameFileds = {};
    cols.array.forEach(el => {
      renameFileds[el.C] = el.N;
    });

    const { DataView } = DataSet;
    const dv = new DataView().source(data);

    dv.transform({
      type: 'rename',
      map: renameFileds
    });

    return dv.rows;

  }

  /**
   * 生成ST表格字段信息
   * @param data 原始结构
   */
  getStColums(data: any) {
    const c = data.map(
      elm => {
        const col: STColumn = {};
        col.title = elm.N;
        col.index = elm.C;
        col.type = elm.T ? elm.T : 'string';
        // col.sorter = (a, b) => a[elm.C] - b[elm.C]

        if (this.supdic.getDic(elm.C).length > 0) {
          col.format = (a) => this.supdic.getdicLabel(elm.C, a[elm.C]);
        }

        col.renderTitle = "clicktitle"

        if (elm.C === '5215') {
          col.render = "miniper";
        }

        return col;
      })

    return c;

  }

  /**
   * 补全行
   * @param data 原始数据
   * @param groupByFiled 分组字段
   * @param orderbyFiled 需要补全的字段
   */
  fillrows(data: any, groupByFiled: any[], orderbyFiled: any[], dataFiled: string) {

    const { DataView } = DataSet;
    const dv = new DataView().source(data);
    dv.transform({
      type: 'fill-rows',
      groupBy: groupByFiled,
      orderBy: orderbyFiled,
      fillBy: 'order' // 默认为 group，可选值：order
    });

    dv.transform({
      type: 'impute',
      field: dataFiled,       // 待补全字段
      groupBy: [], // 分组字段集（传空则不分组）
      method: 'value',  // 补全常量
      value: 0         // 补全的常量为0
    });

    return dv.rows;
  }

  orderData(data: any[], orderFileds: string[], orderType: string = 'ASC') {
    const { DataView } = DataSet;
    const dv = new DataView().source(data);

    dv.transform({
      type: 'sort-by',
      fields: orderFileds, // 根据指定的字段集进行排序，与lodash的sortBy行为一致
      order: orderType === 'ASC' ? 'ASC' : 'DESC'        // 默认为 ASC，DESC 则为逆序
    })

    return dv.rows;

  }

  /**
   * 转化成XY字段
   * @param data 源数据
   * @param xfied X轴的原名称
   * @param yfiled Y轴的原名称
   */
  coverToXy(data: any[], xfied: string, yfiled: string) {

    const { DataView } = DataSet;
    const dv = new DataView().source(data);

    const renameFileds = {};

    renameFileds[xfied] = "x";
    renameFileds[yfiled] = "y";

    dv.transform({
      type: 'rename',
      map: renameFileds
    });

    return dv.rows;

  }

  coverValToPercentVal(data: any[], dimension: string,groupFileds:string[], valFiled: string = "VAL", newValFiled: string = "VAL_pervent") {

    if (!data && data.length < 1) return data;

    const { DataView } = DataSet;
    const dv = new DataView().source(data);

    //  dv.transform({
    //   type: 'aggregate', // 别名summary
    //   fields: [valFiled],        // 统计字段集
    //   operations: ['max'],    // 统计操作集
    //   as: ['VAL_MAX'],            // 存储字段集
    //   groupBy: ['dz']        // 分组字段集
    // })

    dv.transform({
      type: 'percent',
      field: valFiled,           // 统计销量
      dimension,       // 每年的占比
      groupBy: groupFileds, // 以不同产品类别为分组，每个分组内部各自统计占比
      as: newValFiled          // 结果存储在 percent 字段
    });

    const ndata: any[] = dv.rows;

    ndata.map(rec => {
      rec.orgval = rec[valFiled];
      rec[valFiled] = Math.round(rec[newValFiled] * 100);
    });

    return ndata;
  }

} 